package sample

import (
	"database/sql"
	"gorm.io/gorm"
	"organoid_public/domain/sample/model"
	"organoid_public/domain/sample/repository"
	"organoid_public/infrastructure/db"
	"organoid_public/infrastructure/db/gormclient"
	"strings"
)

type SearchRepository struct {
	db *gorm.DB
}

func NewSearchRepository(db db.DefaultDb) repository.Search {
	return &SearchRepository{
		db: db,
	}
}

func (h *SearchRepository) OrganoidPageList(param *repository.OrganoidListParams) (*gormclient.PageList[model.SearchProtocalOrganoid], error) {
	dbInstance := h.db
	if param.Keywords != "" {
		dbInstance = dbInstance.Where("sample_id like @keywords or organoid like @keywords or organism like @keywords or source like @keywords or "+
			"method like @keywords or times like @keywords or co_culture_detail like @keywords or complexity like @keywords or additional_factor like @keywords", sql.Named("keywords", "%"+param.Keywords+"%"))
	}
	if param.Organoid != "" {
		dbInstance = dbInstance.Where("organoid = ?", param.Organoid)
	}
	if param.CoCulture != "" {
		coCultures := strings.Split(param.CoCulture, ",")
		for _, coCulture := range coCultures {
			dbInstance = dbInstance.Where("FIND_IN_SET(?, co_culture_detail)", coCulture)
		}
	}
	if param.CultureMethod != "" {
		dbInstance = dbInstance.Where("method in ?", strings.Split(param.CultureMethod, ","))
	}
	if param.Complexity != "" {
		dbInstance = dbInstance.Where("complexity = ?", param.Complexity)
	}
	if param.Organism != "" {
		dbInstance = dbInstance.Where("organism = ?", param.Organism)
	}
	if param.Source != "" {
		dbInstance = dbInstance.Where("source = ?", param.Source)
	}
	return gormclient.GetPageList[model.SearchProtocalOrganoid](dbInstance, param.Pagination)
}

func (h *SearchRepository) GetOrganoidSampleId(param *repository.OrganoidListParams) ([]string, error) {
	dbInstance := h.db
	if param.Organoid != "" {
		dbInstance = dbInstance.Where("organoid = ?", param.Organoid)
	}
	if param.CoCulture != "" {
		coCultures := strings.Split(param.CoCulture, ",")
		for _, coCulture := range coCultures {
			dbInstance = dbInstance.Where("FIND_IN_SET(?, co_culture_detail)", coCulture)
		}
	}
	if param.CultureMethod != "" {
		cultureMethods := strings.Split(param.CultureMethod, ",")
		for _, cultureMethod := range cultureMethods {
			dbInstance = dbInstance.Where("FIND_IN_SET(?, method)", cultureMethod)
		}
	}
	if param.Complexity != "" {
		dbInstance = dbInstance.Where("complexity = ?", param.Complexity)
	}
	if param.Organism != "" {
		dbInstance = dbInstance.Where("organism = ?", param.Organism)
	}
	if param.Source != "" {
		dbInstance = dbInstance.Where("source = ?", param.Source)
	}
	var res []string
	err := dbInstance.Model(model.SearchProtocalOrganoid{}).Pluck("sample_id", &res).Error
	return res, err
}

func (h *SearchRepository) CoCulturePageList(param *repository.OrganoidListParams) (*gormclient.PageList[model.SearchProtocalCoculture], error) {
	dbInstance := h.db
	if param.Keywords != "" {
		dbInstance = dbInstance.Where("sample_id like @keywords or organoid like @keywords or co_culture like @keywords or times like @keywords or "+
			"medium like @keywords or read_out like @keywords or additional_factor like @keywords", sql.Named("keywords", "%"+param.Keywords+"%"))
	}
	if param.Organoid != "" {
		dbInstance = dbInstance.Where("organoid = ?", param.Organoid)
	}
	if param.CoCulture != "" {
		dbInstance = dbInstance.Where("co_culture in ?", strings.Split(param.CoCulture, ","))
	}
	if param.Organism != "" {
		dbInstance = dbInstance.Where("organism = ?", param.Organism)
	}
	if param.CultureMethod != "" {
		dbInstance = dbInstance.Where("method in ?", strings.Split(param.CultureMethod, ","))
	}
	if param.Complexity != "" {
		dbInstance = dbInstance.Where("complexity = ?", param.Complexity)
	}
	if param.Source != "" {
		dbInstance = dbInstance.Where("source = ?", param.Source)
	}
	return gormclient.GetPageList[model.SearchProtocalCoculture](dbInstance, param.Pagination)
}

func (h *SearchRepository) IdentifyPageList(param *repository.BiomarkerListParams) (*gormclient.PageList[model.SearchBiomarkerIdentified], error) {
	dbInstance := h.db
	if param.Keywords != "" {
		dbInstance = dbInstance.Where("sample_id like @keywords or organoid like @keywords or organism like @keywords or source like @keywords or "+
			"detection_method like @keywords or model_detail like @keywords or biomarker_organoid_detail like @keywords or biomarker_model_detail like @keywords or read_out like @keywords", sql.Named("keywords", "%"+param.Keywords+"%"))
	}
	if param.Organoid != "" {
		dbInstance = dbInstance.Where("organoid = ?", param.Organoid)
	}
	if param.Organism != "" {
		dbInstance = dbInstance.Where("organism = ?", param.Organism)
	}
	if param.Source != "" {
		dbInstance = dbInstance.Where("source = ?", param.Source)
	}
	if param.Period != "" {
		dbInstance = dbInstance.Where("period = ?", param.Period)
	}
	if param.BiomarkerClassfication != "" {
		dbInstance = dbInstance.Where("biomarker_classfication in ?", strings.Split(param.BiomarkerClassfication, ","))
	}
	if param.DetectionMethod != "" {
		dbInstance = dbInstance.Where("detection_method in ?", strings.Split(param.DetectionMethod, ","))
	}
	if param.CoCulture != "" {
		coCultures := strings.Split(param.CoCulture, ",")
		for _, coCulture := range coCultures {
			dbInstance = dbInstance.Where("FIND_IN_SET(?, co_culture_detail)", coCulture)
		}
	}
	if param.DiseaseModeling != "" {
		dbInstance = dbInstance.Where("disease_modeling in ?", strings.Split(param.DiseaseModeling, ","))
	}
	if param.DrugTest != "" {
		dbInstance = dbInstance.Where("drug_test = ?", param.DrugTest)
	}
	return gormclient.GetPageList[model.SearchBiomarkerIdentified](dbInstance, param.Pagination)
}

func (h *SearchRepository) PotentialPageList(param *repository.BiomarkerListParams) (*gormclient.PageList[model.SearchBiomarkerPotential], error) {
	dbInstance := h.db
	if param.Keywords != "" {
		dbInstance = dbInstance.Where("potential_biomarker like @keywords or organoid like @keywords or organism like @keywords or application like @keywords or "+
			"experimental_strategy_rna_seq_detail like @keywords or experimental_strategy_scrna_seq_detail like @keywords", sql.Named("keywords", "%"+param.Keywords+"%"))
	}
	if param.Organoid != "" {
		dbInstance = dbInstance.Where("organoid = ?", param.Organoid)
	}
	if param.Organism != "" {
		dbInstance = dbInstance.Where("organism = ?", param.Organism)
	}
	if param.Source != "" {
		dbInstance = dbInstance.Where("source = ?", param.Source)
	}
	if param.Period != "" {
		dbInstance = dbInstance.Where("period = ?", param.Period)
	}
	if param.BiomarkerClassfication != "" {
		dbInstance = dbInstance.Where("biomarker_classfication in ?", strings.Split(param.BiomarkerClassfication, ","))
	}
	if param.DetectionMethod != "" {
		dbInstance = dbInstance.Where("detection_method in ?", strings.Split(param.DetectionMethod, ","))
	}
	if param.CoCulture != "" {
		coCultures := strings.Split(param.CoCulture, ",")
		for _, coCulture := range coCultures {
			dbInstance = dbInstance.Where("FIND_IN_SET(?, co_culture_detail)", coCulture)
		}
	}
	if param.DiseaseModeling != "" {
		dbInstance = dbInstance.Where("disease_modeling in ?", strings.Split(param.DiseaseModeling, ","))
	}
	if param.DrugTest != "" {
		dbInstance = dbInstance.Where("drug_test = ?", param.DrugTest)
	}
	return gormclient.GetPageList[model.SearchBiomarkerPotential](dbInstance, param.Pagination)
}
